from app.models.user_info import UserInfo
from app.models.body_metrics import BodyMetrics
from app.models.diseases import Diseases
from app.models.user_diseases import UserDiseases
from app.models.health_metrics import HealthMetrics
from app.models.workout_record import WorkoutRecord
from app.models.nutrient_reference_intakes import NutrientReferenceIntakes
from app.models.user_factor import UserFactor
from app.models.rdi import RDI
from app import db
from app.config import APP_ID,APP_SECRET
import requests
from datetime import datetime, timedelta


class UserService:

    def wx_login(self, code):
        """通过微信的 code 获取 openid 和 session_key"""
        url = f"https://api.weixin.qq.com/sns/jscode2session?appid={APP_ID}&secret={APP_SECRET}&js_code={code}&grant_type=authorization_code"
        response = requests.get(url)
        data = response.json()

        if 'errcode' in data:
            raise ValueError('Failed to get session from WeChat')

        openid = data.get('openid')
        session_key = data.get('session_key')

        # 查询数据库，检查用户是否已经注册
        user = UserInfo.query.filter_by(openid=openid).first()
        if not user:
            # 用户首次登录，创建用户信息
            user = UserInfo(openid=openid)
            # 初始化用户的 body_metrics 和 health_metrics
            body_metrics = BodyMetrics(user_id=user.user_id)
            health_metrics = HealthMetrics(user_id=user.user_id)
            user_factor = UserFactor(user_id=user.user_id)

            # 将新用户及相关数据保存到数据库
            db.session.add(user)
            db.session.add(body_metrics)
            db.session.add(health_metrics)
            db.session.add(user_factor)
            db.session.commit()


        return user, session_key


    def update_user_info(self, user_info):
        try:
            # 解析用户信息
            openid = user_info.get('openid')
            avatar_url = user_info.get('avatarUrl')
            nick_name = user_info.get('nickName')
            gender = user_info.get('gender')
            country = user_info.get('country')
            province = user_info.get('province')
            city = user_info.get('city')

            # 查询数据库中是否存在该用户
            user = UserInfo.query.filter_by(openid=openid).first()

            if user:
                # 如果用户存在，更新用户信息
                user.avatar_url = avatar_url
                user.nick_name = nick_name
                user.gender = gender
                user.country = country
                user.province = province
                user.city = city
            else:
                # 如果用户不存在，则插入新的用户记录
                user = UserInfo(
                    openid=openid,
                    avatar_url=avatar_url,
                    nick_name=nick_name,
                    gender=gender,
                    country=country,
                    province=province,
                    city=city
                )
                db.session.add(user)  # 插入新记录

            db.session.commit()  # 提交事务
            return {"success": True, "message": "用户信息更新成功"}

        except Exception as e:
            db.session.rollback()  # 如果发生错误，回滚事务
            return {"success": False, "message": f"更新失败: {str(e)}"}


    def get_user_body_info(self, user_id):
        # 处理业务逻辑，获取用户信息
        # 获取用户基本信息
        user = UserInfo.query.get(user_id)
        if not user:
            return None, "User not found"

        # 获取用户身体数据
        body_metrics = BodyMetrics.query.filter_by(user_id=user_id).first()
        if not body_metrics:
            return None, "Body metrics not found"

        # 获取用户健康数据
        health_metrics = HealthMetrics.query.filter_by(user_id=user_id).first()
        if not health_metrics:
            return None, "Health metrics not found"


        user_factor, error = self.adjust_factor(user_id, '', '')
        if error:
            print(error)
            return None, error


        # 获取用户疾病数据
        user_diseases = db.session.query(Diseases).join(UserDiseases).filter(UserDiseases.user_id == user_id).all()

        # 组装返回的bodyInfo数据
        body_info = {
            "gender": user.gender,
            "birthday": user.birthday,
            "age": user.age,
            'calories': round(user_factor.calories_intake*100),
            'carb_ratio': user_factor.carb_ratio/100,
            'prot_ratio': user_factor.prot_ratio/100,
            'fat_ratio': user_factor.fat_ratio/100,
            "doSport": user.do_sport,
            "hasDisease": user.has_disease,
            "height": body_metrics.height *100,
            "weight": body_metrics.weight,
            "waist": body_metrics.waist,
            "hip": body_metrics.hip,
            "BMI": body_metrics.BMI,
            "bodyFat":body_metrics.body_fat,
            "waistToHipRatio": body_metrics.waist_hip_ratio,
            "BMR": body_metrics.BMR,
            "disease": [{"id": idx + 1, "name": disease.name} for idx, disease in enumerate(user_diseases)],
            "uricAcid": health_metrics.uric_acid,
            "bloodFat": health_metrics.blood_fat,
            "bloodSugar": health_metrics.blood_sugar,
            "bodyFatRate": body_metrics.body_fat,
            "visceralFatArea": health_metrics.visceral_fat_area,
            "muscleMass": health_metrics.muscle_mass,
            'lifeStyle': "运动员",
            "target": "增肌"
        }

        return body_info, None


    def update_user_body_info(self, user_id, data):
        try:
            print(data['bodyInfo'])
            body_info = data['bodyInfo']
            # 获取用户信息
            user = UserInfo.query.get(user_id)
            if not user:
                return None, "User not found"

            # 获取用户身体数据
            body_metrics = BodyMetrics.query.filter_by(user_id=user_id).first()
            if not body_metrics:
                # 如果没有身体数据，则创建新的 BodyMetrics 记录
                body_metrics = BodyMetrics(user_id=user_id)
                db.session.add(body_metrics)

            # 获取用户健康数据
            health_metrics = HealthMetrics.query.filter_by(user_id=user_id).first()
            if not health_metrics:
                # 如果没有健康数据，则创建新的 HealthMetrics 记录
                health_metrics = HealthMetrics(user_id=user_id)
                db.session.add(health_metrics)

            # 验证传入的 body_info 数据完整性和格式
            required_fields = ['gender', 'birthday', 'age', 'hasDisease', 'doSport',
                               'height', 'weight', 'waist', 'hip', 'BMI', 'waistToHipRatio',
                               'BMR', 'uricAcid', 'bloodFat', 'bloodSugar', 'bodyFatRate',
                               'visceralFatArea', 'muscleMass']
            for field in required_fields:
                if field not in body_info:
                    return None, f"Missing required field: {field}"

            lifestyle_type = body_info['lifeStyle']
            target = body_info['target']
            user_factor, error = self.adjust_factor(user_id, lifestyle_type, target)
            if error:
                return None, error


            # 更新用户基本信息
            user.gender = 1 if body_info['gender'] == '女' else 0
            user.birthday = body_info['birthday']
            user.age = body_info['age']
            user.has_disease = True if len(body_info['disease']) > 0 else False
            user.do_sport = body_info.get('doSport', False)
            user.lifestyle_type = lifestyle_type
            user.target = target

            # 更新身体数据
            body_metrics.height = float(body_info['height']) / 100  # 身高转换为米
            body_metrics.weight = body_info['weight']
            body_metrics.waist = body_info['waist']
            body_metrics.hip = body_info['hip']
            body_metrics.BMI = body_info['BMI']
            body_metrics.waist_hip_ratio = body_info['waistToHipRatio']
            body_metrics.BMR = body_info['BMR']

            # 更新健康数据
            health_metrics.uric_acid = body_info['uricAcid']
            health_metrics.blood_fat = body_info['bloodFat']
            health_metrics.blood_sugar = body_info['bloodSugar']
            body_metrics.body_fat = body_info['bodyFatRate']
            health_metrics.visceral_fat_area = body_info['visceralFatArea']
            health_metrics.muscle_mass = body_info['muscleMass']

            # 提交数据库更新
            db.session.commit()  # 保存更新到数据库

            # 处理疾病数据
            # diseases = []
            # 清除当前用户所有的疾病记录
            # 获取用户疾病数据
            # user_diseases = db.session.query(Diseases).join(UserDiseases).filter(UserDiseases.user_id == user_id).all()
            # # user_diseases = UserDiseases.query.filter_by(user_id=user_id).all()
            # for disease in user_diseases:
            #     db.session.delete(disease)
            #
            # # 添加新的疾病记录
            # for idx, disease in enumerate(body_info.get('disease', [])):
            #     disease_entry = Diseases.query.filter_by(name=disease['name']).first()
            #     if disease_entry:
            #         # 创建新的用户疾病关联
            #         user_disease = UserDiseases(user_id=user_id, disease_id=disease_entry.disease_id)
            #         db.session.add(user_disease)
            #         # 将疾病信息加入到返回数据中
            #         diseases.append({"id": disease_entry.disease_id, "name": disease_entry.name})
            diseases = body_info['disease'] # 业务代码待完善

            # 提交疾病更新
            # db.session.commit()


            # 返回更新后的身体信息
            return {
                "birthday": user.birthday,
                "age": user.age,
                "gender": user.gender,
                "lifestyle_type": user.lifestyle_type,
                'calories': user_factor.calories_intake * 1000,  # Adjusted value from body_info1
                'carb_ratio': user_factor.carb_ratio,  # Already in body_info2
                'prot_ratio': user_factor.prot_ratio,  # Already in body_info2
                'fat_ratio': user_factor.fat_ratio,  # Already in body_info2
                "weight": body_metrics.weight,
                "height": body_metrics.height *100,
                "BMI": body_metrics.BMI,
                "waist": body_metrics.waist,
                "hip": body_metrics.hip,
                "waistToHipRatio": body_metrics.waist_hip_ratio,  # Already in body_info2
                "BMR": body_metrics.BMR,
                "body_fat": body_metrics.body_fat,
                "biceps": body_metrics.biceps,  # Not in body_info1, included here
                "chest": body_metrics.chest,  # Not in body_info1, included here
                "thigh": body_metrics.thigh,  # Not in body_info1, included here
                "heart_rate_rest": body_metrics.heart_rate_rest,  # Not in body_info1, included here
                "frequency_per_week": body_metrics.frequency_per_week,  # Not in body_info1, included here
                "dream_weight": body_metrics.dream_weight,  # Not in body_info1, included here
                "diastolic": health_metrics.diastolic,  # Not in body_info1, included here
                "systolic": health_metrics.systolic,  # Not in body_info1, included here
                "visceral_fat_area": health_metrics.visceral_fat_area,  # Already in body_info1
                "muscle_mass": health_metrics.muscle_mass,  # Already in body_info1
                "disease": diseases,  # Already in body_info1
                "uricAcid": health_metrics.uric_acid,  # Already in body_info1
                "bloodFat": health_metrics.blood_fat,  # Already in body_info1
                "bloodSugar": health_metrics.blood_sugar,  # Already in body_info1
                "body_fat_rate": body_metrics.body_fat,  # Included from body_info1 as body_fat_rate (duplicate of body_fat)
                "lifeStyle": "运动员",  # Not in body_info2, included here
                "target": "增肌"  # Not in body_info2, included here
            }, None

        except Exception as e:

            db.session.rollback()  # 回滚事务，防止错误时提交无效数据
            return None, f"An error occurred while updating body info: {str(e)}"


    def calculate_adjustment_factor(self, user_id):
        # 获取最新的锻炼记录
        workout_data = WorkoutRecord.query.filter_by(user_id=user_id).order_by(WorkoutRecord.created_at.desc()).first()

        if not workout_data:
            return 1.0  # 如果没有记录，返回默认因子

        adjustment_factor = 1.0

        # 基于用户的锻炼数据动态调整因子
        if workout_data.BMI < 18.5:
            adjustment_factor += 0.2  # 体重过轻，增加能量摄入
        elif workout_data.BMI > 25:
            adjustment_factor -= 0.1  # 体重过重，减少脂肪摄入

        if workout_data.exercise_intensity == '高':
            adjustment_factor += 0.3  # 高强度锻炼增加蛋白质和碳水化合物
        elif workout_data.exercise_intensity == '低':
            adjustment_factor -= 0.1  # 低强度锻炼减少摄入

        if workout_data.calories_burn > 500:
            adjustment_factor += 0.2  # 高卡路里消耗增加摄入
        elif workout_data.calories_burn < 200:
            adjustment_factor -= 0.1  # 低卡路里消耗减少摄入

        if workout_data.body_fat > 25:
            adjustment_factor -= 0.1  # 高体脂减少脂肪摄入
        elif workout_data.body_fat < 15:
            adjustment_factor += 0.2  # 低体脂增加蛋白质摄入

        return adjustment_factor

    def get_actual_recommendation(self, user_id, nutrient_id):
        # 计算调整因子
        adjustment_factor = self.calculate_adjustment_factor(user_id)

        # 获取营养素推荐摄入量数据
        nutrient_data = NutrientReferenceIntakes.query.filter_by(id=nutrient_id).first()

        if not nutrient_data:
            return None  # 如果没有找到数据

        # 根据调整因子计算实际推荐摄入量
        actual_recommendation = nutrient_data.RNI * adjustment_factor
        return actual_recommendation

    def adjust_factor(self, user_id, lifestyle_type, target):
        """
        根据用户的生活方式和健康目标初始化或更新 user_factor 表。
        :param user_id: 用户ID
        :param lifestyle_type: 用户的生活方式类型 ('运动员', '孕妇', '老年人', '糖尿病患者', '减肥')
        :param target: 用户的健康目标 ('减脂', '增肌', '维持体重', '糖尿病管理')
        :return: 调整后的 user_factor 记录
        # 用法示例:
        # 调用 `adjust_factor` 函数以初始化或更新用户的生活方式因子及健康目标因子
        lifestyle_type = '运动员'  # 用户的生活方式
        target = '增肌'  # 用户的健康目标
        user_id = 'user123'  # 用户ID
        user_factor, error = UserFactor.adjust_factor(user_id, lifestyle_type, target)
        """
        # 1. 获取用户的运动频率
        last_week_date = datetime.now() - timedelta(days=7)
        workout_frequency = WorkoutRecord.query.filter(
            WorkoutRecord.user_id == user_id,
            WorkoutRecord.created_at >= last_week_date
        ).count()

        # 2. 查询 RDI 表以获取该用户对应年龄和性别的营养素推荐值
        user = UserInfo.query.get(user_id)
        if not user:
            return None, "User not found"
        # 根据 user.gender 值调整为对应的 Enum 类型
        if user.gender == 0:
            gender = 'Male'
        elif user.gender == 1:
            gender = 'Female'
        else:
            gender = 'Other'  # 如果有'Other'性别选项


        rdis = RDI.query.filter(
            RDI.age_low <= user.age, RDI.age_high >= user.age, RDI.gender == gender
        ).all()

        if not rdis:
            return None, "No RDI data found for the given user age and gender"

        # 3. 计算每天推荐的热量摄入（calories_intake）
        calories_factor = None
        if 0 <= workout_frequency <= 3:
            # 一等
            calories_factor = 1.0  # Adjust as needed
        elif 3 <= workout_frequency <= 5:
            # 二等
            calories_factor = 1.2  # Adjust as needed
        else:
            # 三等或无
            calories_factor = 1.4  # Adjust as needed

        # 4. 初始化或更新 user_factor 记录
        user_factor = UserFactor.query.filter_by(user_id=user_id).first()
        if user_factor:
            # 已存在记录，只进行调整
            if lifestyle_type:
                user_factor.adjust_for_target(target)
            else:
                user_factor.adjust_for_lifestyle(lifestyle_type)
        else:
            # 初始化 user_factor 记录
            user_factor = UserFactor(user_id=user_id, lifestyle_type=lifestyle_type, calories_factor=calories_factor)
            user_factor.calories_intake = next((rdi.RNI for rdi in rdis if rdi.nutrient_name == '能量(PAL_I)(MJ/d)'),
                                               0) * calories_factor
            user_factor.carb_ratio = next((rdi.AMDR_min for rdi in rdis if rdi.nutrient_name == '总碳水化合物(%E)'), 0)
            user_factor.prot_ratio = next((rdi.AMDR_max for rdi in rdis if rdi.nutrient_name == '蛋白质(g/d)'), 0)
            user_factor.fat_ratio = next((rdi.AMDR_max for rdi in rdis if rdi.nutrient_name == '总脂肪(%E)'), 0)
            db.session.add(user_factor)

        db.session.commit()


        return user_factor, None


    def create_user_factor(self, data):
        """
        创建用户，并在 `user_factor` 表中为该用户初始化默认调整因子。
        """
        # 验证必要字段
        required_fields = ['user_id', 'gender', 'age', 'lifestyle_type', 'phone']
        if not all(field in data for field in required_fields):
            raise ValueError("Missing required fields")

        try:
            # 创建新用户
            new_user = UserInfo(
                user_id=data['user_id'],
                openid=data.get('openid'),
                card_id=data.get('card_id'),
                phone=data['phone'],
                gender=data['gender'],
                birthday=data.get('birthday'),
                age=data.get('age'),
                province=data.get('province'),
                city=data.get('city'),
                district=data.get('district'),
                has_disease=data.get('has_disease', False),
                do_sport=data.get('do_sport', False),
                lifestyle_type=data.get('lifestyle_type'),
                target=data['target']  # 用户的健康目标字段
            )

            # 将用户保存到数据库
            db.session.add(new_user)
            db.session.commit()

            # 初始化用户的膳食因子
            self.initialize_user_factor(new_user)


            return new_user

        except Exception as e:
            # 处理任何异常
            db.session.rollback()
            raise e

    def initialize_user_factor(self, user_id):
        """初始化用户的膳食因子，包括卡路里、蛋白质、脂肪等调整因子"""
        try:
            # 获取用户信息
            user_info = UserInfo.query.get(user_id)
            if not user_info:
                raise ValueError("User not found")

            # 获取用户的健康目标，生活方式类型，年龄和性别
            target = user_info.target  # 用户健康目标
            lifestyle_type = user_info.lifestyle_type  # 生活方式类型，如运动员、孕妇、老年人等
            age = user_info.age
            gender = user_info.gender

            # 获取 RDI 数据，按年龄段和性别进行查询
            rdi_data = RDI.query.filter(
                RDI.gender == gender,
                RDI.age_low <= age,
                RDI.age_high >= age
            ).all()

            # 用户因子的存储字典
            user_factors = {}

            # 遍历 RDI 数据，按照目标与生活方式调整因子
            for rdi in rdi_data:
                if target:
                    # 如果用户有健康目标，则根据目标调整膳食因子
                    adjusted_rdi = rdi.adjust_for_target(rdi, target)
                else:
                    # 如果没有健康目标，则根据生活方式调整膳食因子
                    adjusted_rdi = rdi.adjust_for_lifestyle(lifestyle_type)

                # 确保调整后的 RDI 实例不为空
                if adjusted_rdi:
                    # 根据调整后的 RDI 实例存储膳食因子
                    if adjusted_rdi.nutrient_name == '能量(PAL_I)(MJ/d)':
                        user_factors['calories_factor'] = adjusted_rdi.RNI  # 记录卡路里因子
                    elif adjusted_rdi.nutrient_name == '蛋白质(g/d)':
                        user_factors['protein_factor'] = adjusted_rdi.RNI  # 记录蛋白质因子
                    elif adjusted_rdi.nutrient_name == '总碳水化合物(%E)':
                        user_factors['carb_ratio'] = adjusted_rdi.AMDR_min  # 记录碳水化合物比率
                    elif adjusted_rdi.nutrient_name == '总脂肪(%E)':
                        user_factors['fat_ratio'] = adjusted_rdi.AMDR_min  # 记录脂肪比率
                    elif adjusted_rdi.nutrient_name == '水(mL/d)_low':
                        user_factors['water_factor_low'] = adjusted_rdi.AI  # 记录低限水量
                    elif adjusted_rdi.nutrient_name == '水(mL/d)_high':
                        user_factors['water_factor_high'] = adjusted_rdi.AI  # 记录高限水量

            # 保存或更新用户因子到数据库
            user_factor = UserFactor.query.filter_by(user_id=user_id).first()
            if user_factor:
                # 如果已有用户因子，更新现有记录
                user_factor.calories_factor = user_factors.get('calories_factor', user_factor.calories_factor)
                user_factor.protein_factor = user_factors.get('protein_factor', user_factor.protein_factor)
                user_factor.carb_ratio = user_factors.get('carb_ratio', user_factor.carb_ratio)
                user_factor.fat_ratio = user_factors.get('fat_ratio', user_factor.fat_ratio)
                user_factor.water_factor_low = user_factors.get('water_factor_low', user_factor.water_factor_low)
                user_factor.water_factor_high = user_factors.get('water_factor_high', user_factor.water_factor_high)
            else:
                # 创建新的用户因子记录
                user_factor = UserFactor(
                    user_id=user_id,
                    calories_factor=user_factors.get('calories_factor'),
                    protein_factor=user_factors.get('protein_factor'),
                    carb_ratio=user_factors.get('carb_ratio'),
                    fat_ratio=user_factors.get('fat_ratio'),
                    water_factor_low=user_factors.get('water_factor_low'),
                    water_factor_high=user_factors.get('water_factor_high')
                )
                db.session.add(user_factor)

            # 提交到数据库
            db.session.commit()

            return {"status": "success", "message": "User factors initialized successfully"}

        except Exception as e:
            # 如果出现异常，回滚事务
            db.session.rollback()
            return {"status": "error", "message": str(e)}, 500

